
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
using System;
using System.Collections;
using System.IO;
using System.Net;
using System.Reflection;
using System.Runtime.InteropServices;



namespace Swaf.Script
{
	/// <summary>
	/// Provides support for any ActiveX scripting language installed in the running environment.  
	/// Offers ability to load scripts, create script objects, and call script functions for multiple
	/// scripting languages simultaniously.</summary>
	public class ScriptManager : IScriptManager
	{
		public ScriptManager()
		{
			m_loadedScripts = new Hashtable();
			m_scriptEngines = new Hashtable();
		}

		public void completeInitialization()
		{
			foreach(IScriptEnvironment e in m_scriptEngines.Values)
				e.completeInitialization();
		}

		public void loadScript(string scriptLanguage, Uri scriptLocation)
		{
			if(!m_loadedScripts.Contains(scriptLocation))
			{
				WebRequest r = WebRequest.Create(scriptLocation);
				string content = null;
				try {
					StreamReader strm = new StreamReader(r.GetResponse().GetResponseStream());
					content = strm.ReadToEnd();
					strm.Close();
				}catch(Exception){}
				if(content != null)
				{
					m_loadedScripts[scriptLocation] = scriptLocation;
					getScriptingEngine(scriptLanguage).loadScript(scriptLocation.ToString(), content);
				}
				else
					Application.currentApp.Log.println(Application.DEFAULT_FRAMEWORK_LOG_LEVEL,"Couldnt read contents from " + scriptLocation.AbsoluteUri);

			}
		}

		public void defineFunction(string scriptLanguage, string functionName, string[] paramNames, string functionBody)
		{
			string scriptFunction = null;

			//TODO: This code doesn't belong here and should be done by the specific scripting engine.  This class should
			//have no direct knowledge of any specific script language.
			if(String.Compare(scriptLanguage, "jscript", true) == 0 || String.Compare(scriptLanguage, "jscript.net", true) == 0)
				scriptFunction = String.Format("function {0}({1})\n{{ {2} }}\n", functionName, String.Join(",", paramNames), functionBody);
			else if(String.Compare(scriptLanguage, "vbscript", true) == 0)
				scriptFunction = String.Format("function {0}({1})\n{2}\n{0}=retval\nend function\n", functionName, String.Join(", ", paramNames), functionBody);
			else
				scriptFunction = functionBody;

			if(scriptFunction != null)
				getScriptingEngine(scriptLanguage).loadScript(functionName, scriptFunction);
			else
				throw new Exception("Unknown scripting language '" + scriptLanguage + "'");
		}

		public void loadScript(string scriptLanguage, string scriptCode)
		{
			getScriptingEngine(scriptLanguage).loadScript("Anonymous Script Block", scriptCode);
		}

		public object createObject(string scriptLanguage, string factory)
		{
			return getScriptingEngine(scriptLanguage).createObject(factory);
		}

		public object invokeScriptFunction(string scriptLanguage, string functionName, object[] functionParams)
		{
			return getScriptingEngine(scriptLanguage).invokeScriptFunction(functionName, functionParams);
		}

		public bool isScriptFunctionDefined(string scriptLanguage, string functionName)
		{
			return getScriptingEngine(scriptLanguage).isScriptFunctionDefined(functionName);
		}

		public void addGlobalNamedObject(string name, object globalObj)
		{
		}
/*
		public object getGlobalObject(string scriptLanguage)
		{
			return getScriptingEngine(scriptLanguage).GlobalObject;
		}
*/
		protected IScriptEnvironment getScriptingEngine(string scriptLanguage)
		{
			if(!m_scriptEngines.Contains(scriptLanguage))
			{
				IClassFactory languageFactory = Application.currentApp.factories["ScriptLanguages"];
				m_scriptEngines[scriptLanguage] = languageFactory.createFromNickName(scriptLanguage, scriptLanguage);
			}
			return (IScriptEnvironment)m_scriptEngines[scriptLanguage];
		}


		protected IDictionary m_loadedScripts;
		protected IDictionary m_scriptEngines;
	}


}
